{
open Lexing
open Parser
open Core_kernel.Std

exception SyntaxError of string

let next_line lexbuf =
  let pos = lexbuf.lex_curr_p in
  lexbuf.lex_curr_p <-
    { pos with
      pos_bol = lexbuf.lex_curr_pos;
      pos_lnum = pos.pos_lnum + 1 }

let keyword_map : token String.Map.t =
  [
    "declare"  , K_declare;
    "encoding" , K_encoding;
    "feedback" , K_feedback;
    "input"    , K_input;
    "module"   , K_module;
    "output"   , K_output;
    "parameter", K_parameter;
    "path"     , K_path;
    "pipeline" , K_pipeline;
    "stage"    , K_stage;
    "wire"     , K_wire;
  ]
  |> String.Map.of_alist_exn
}

let int = ('0' | ['1'-'9'] ['0'-'9']*)
let white = [' ' '\t']+
let newline = '\n'
let id = ['a'-'z' 'A'-'Z' '_'] ['a'-'z' 'A'-'Z' '_' '0'-'9']*
let comment = "//" [^'\n']* '\n'

let bit = '0'|'1'

rule read = parse
  | white { read lexbuf }
  | comment { next_line lexbuf; read lexbuf }
  | newline { next_line lexbuf; read lexbuf }
  | int { Int (int_of_string (Lexing.lexeme lexbuf)) }
  | "'b" (bit+ as b) { BitVector (int_of_string ("0b"^b)) }
  | id
    { let s = Lexing.lexeme lexbuf in
      match String.Map.find keyword_map s with
      | Some t -> t
      | None -> Ident s }
  | "--" { Dash }
  | "->" { Arrow }
  | '(' { LParen }
  | ')' { RParen }
  | '.' { Dot }
  | ':' { Colon }
  | ';' { Semi }
  | '=' { Eq }
  | '[' { LBrack }
  | ']' { RBrack }
  | '{' { LBrace }
  | '}' { RBrace }
  (* | '@' id
    { let lexeme = Lexing.lexeme lexbuf in
      AtKeyword (String.sub 1 (String.length lexeme - 1) lexeme) }
  | _ { raise (SyntaxError ("Unexpected character: " ^ Lexing.lexeme lexbuf)) } *)
  | eof { EOF }
